﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TCPlib.OML
{
    public class TypeConvert
    {
        /// <summary>
        /// 将字符串转换为字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <param name="isLittleEndian"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public byte[] FloatsToBytes(string value, bool isLittleEndian)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new ArgumentException("Input string is null or empty.", nameof(value));
            }

            try
            {
                // 去除空格并转换为 float
                float floatValue = float.Parse(value.Trim());

                // 将 float 转换为字节数组
                byte[] floatBytes = BitConverter.GetBytes(floatValue);

                // 根据需要调整字节序
                if (isLittleEndian == false)
                {
                    SwapBytes(floatBytes);
                }
                //short[] shortArray = new short[floatBytes.Length / 2];
                //Buffer.BlockCopy(floatBytes, 0, shortArray, 0, floatBytes.Length);

                return floatBytes;
            }
            catch (FormatException)
            {
                throw new ArgumentException("Input string is not a valid float.", nameof(value));
            }
            catch (OverflowException)
            {
                throw new ArgumentException("Input string represents a number that is too large or too small for a float.", nameof(value));
            }

        }

        /// <summary>
        /// bool数组转换字节数组
        /// </summary>
        /// <param name="bitArray"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public byte[] BoolsToBytes(bool[] bitArray)
        {
            if (bitArray == null)
            {
                throw new ArgumentException("无效的位数组");
            }

            int byteCount = (bitArray.Length + 7) / 8; // 计算字节数组的长度，向上取整，满足最小字节为八位
            byte[] byteArray = new byte[byteCount];

            for (int i = 0; i < bitArray.Length; i++)
            {
                if (bitArray[i])
                {
                    byteArray[i / 8] |= (byte)(1 << (i % 8)); // 将位设置到正确的位置
                }
            }
            Array.Reverse(byteArray);
            return byteArray;
        }

        /// <summary>
        /// int数组转换字节数组
        /// </summary>
        /// <param name="value"></param>
        /// <param name="isLittleEndian"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public byte[] IntsToBytes(string value, bool isLittleEndian)
        {
            if (value == null)
            {
                throw new ArgumentException("无效的int数组");
            }
            try
            {
                // 去除空格并转换为 float
                int floatValue = int.Parse(value.Trim());

                // 将 float 转换为字节数组
                byte[] bytes = BitConverter.GetBytes(floatValue);

                // 根据需要调整字节序
                if (isLittleEndian == false)
                {
                    SwapBytes(bytes);
                }
                return bytes;
            }
            catch (FormatException)
            {
                throw new ArgumentException("Input string is not a valid float.", nameof(value));
            }
            catch (OverflowException)
            {
                throw new ArgumentException("Input string represents a number that is too large or too small for a float.", nameof(value));
            }
        }

        /// <summary>
        /// 将字节数组转换为 float 数组
        /// </summary>
        /// <param name="byteArray"></param>
        /// <param name="isLittleEndian"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public float[] BytesToFloats(byte[] byteArray, bool isLittleEndian)
        {

            if (byteArray == null || byteArray.Length % 4 != 0)
            {
                throw new ArgumentException("无效的字节数组");
            }

            float[] floatArray = new float[byteArray.Length / 4];
            byte[] tempArray = new byte[4];

            for (int i = 0; i < byteArray.Length; i += 4)
            {
                Array.Copy(byteArray, i, tempArray, 0, 4);

                if (isLittleEndian == false)
                {
                    SwapBytes(tempArray);
                }
                float result = BitConverter.ToSingle(tempArray, 0);
                result = (float)Math.Round(result, 3);
                floatArray[i / 4] = result;
            }

            return floatArray;
        }
        
        /// <summary>
        /// 将字节数组转换为 int 数组
        /// </summary>
        /// <param name="byteArray"></param>
        /// <param name="isLittleEndian"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public int[] BytesToInts(byte[] byteArray, bool isLittleEndian)
        {
            if (byteArray == null || byteArray.Length % 4 != 0)
            {
                throw new ArgumentException("无效的字节数组");
            }

            int[] intArray = new int[byteArray.Length / 4];
            byte[] tempArray = new byte[4];

            for (int i = 0; i < byteArray.Length; i += 4)
            {
                Array.Copy(byteArray, i, tempArray, 0, 4);

                if (isLittleEndian == false)
                {
                    SwapBytes(tempArray);
                }
                else
                {
                    // 反转字节数组
                    Array.Reverse(tempArray);
                }
                int result = BitConverter.ToInt32(tempArray, 0);
                intArray[i / 4] = result;
            }

            return intArray;
        }

        /// <summary>
        /// 将字节数组转换为 short 数组
        /// </summary>
        /// <param name="byteArray"></param>
        /// <param name="isLittleEndian"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public short[] BytesToShorts(byte[] byteArray, bool isLittleEndian)
        {
            if (byteArray == null || byteArray.Length % 2 != 0)
            {
                throw new ArgumentException("无效的字节数组");
            }

            short[] shortArray = new short[byteArray.Length / 2];
            byte[] tempArray = new byte[2];

            for (int i = 0; i < byteArray.Length; i += 2)
            {
                Array.Copy(byteArray, i, tempArray, 0, 2);

                if (isLittleEndian == false)
                {
                    Array.Reverse(tempArray); // 反转字节数组
                }

                short result = BitConverter.ToInt16(tempArray, 0);
                shortArray[i / 2] = result;
            }

            return shortArray;
        }

        /// <summary>
        /// 将short数组转换为 bool 数组
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public bool[] ShortsToBools(short[] byteArray)
        {
            if (byteArray == null)
            {
                throw new ArgumentException("无效的短整型数组");
            }

            bool[] bitArray = new bool[byteArray.Length * 16];

            for (int i = 0; i < byteArray.Length; i++)
            {
                for (int bit = 0; bit < 16; bit++)
                {
                    bitArray[i * 16 + bit] = (byteArray[i] & (1 << bit)) != 0;
                }
            }
            return bitArray;
        }

        /// <summary>
        /// 用于字节数组的高八位和低八位转换，欧姆龙PLC需要高八位和低八位转换
        /// </summary>
        /// <param name="bytes"></param>
        public void SwapBytes(byte[] bytes)
        {
            // 前16位高八位和低八位交换
            byte temp = bytes[0];
            bytes[0] = bytes[1];
            bytes[1] = temp;

            // 后16位高八位和低八位交换
            temp = bytes[2];
            bytes[2] = bytes[3];
            bytes[3] = temp;
        }

    }
}
